/*
 * an editor sppourt advance syntax highlight
 * zhangxuecheng1985@gmail.com
 * 2009-4-25
 */

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char tokenlist[64] =
  { '#', '!', '%', '&', '*', '(', ')', '-', '=', '+', '/', '>', '.', ',', '<',']', '[', '~', '"', '\'', '\\', '{','}',';',':',' ','\n','\r'};
int is_token (char c)
{
  int i = 0;
  int flag = 0;
  int l = sizeof (tokenlist) / sizeof (tokenlist[0]);
  for (i = 0; i < l; i++)
    {
      if (c == tokenlist[i])
	{
	  flag = 1;
	  break;
	}
    }

  return flag;
}

char keywordlist[32][32]={
    "int",
    "include",
    "unsigned",
    "short",
    "return",
    "void",
    "if",
    "else",
    "char",
    "for",
    "long",
    "switch",
    "case",
    "goto",
    "break",
    "continue",
    "sizeof"
};

int is_keyword(const char *s,int l)
{
    int i = 0;
    int flen = 0;
    int flag = 0;
    int ll = 0;

    flen=sizeof(keywordlist)/sizeof(keywordlist[0][0]);
    for(i=0;i<flen;i++)
    {
	ll=sizeof(keywordlist[0])/sizeof(keywordlist[0][0]);
	if(!memcmp(s,keywordlist[i],ll))
	{
	    flag = 1;
	    //printf("is keyword\n");
	    break;
	}
    }

    return flag;
}

int
main (int argc, char *argv[])
{
  static GtkWidget *window=NULL;
  GtkWidget *scrolled_window=NULL;
  GtkWidget *view=NULL;
  GtkWidget *vbox=NULL;

  GtkTextBuffer *buffer;
  GtkTextIter start, end;
  GtkTextIter iter;

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size (GTK_WINDOW (window), 1024, 768);
  gtk_window_set_title (GTK_WINDOW (window), "zhangxuecheng's editer");
  gtk_container_set_border_width (GTK_CONTAINER (window), 0);
  GTK_WINDOW (window)->allow_shrink = TRUE;

  vbox = gtk_vbox_new (FALSE, 0);
  view = gtk_text_view_new ();
  gtk_widget_add_events (view, GDK_BUTTON_PRESS_MASK);
  gtk_box_pack_start (GTK_BOX (vbox), view, TRUE, TRUE, 0);

  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
  gtk_text_buffer_create_tag (buffer, "token", "foreground", "red", NULL);
  gtk_text_buffer_create_tag (buffer, "keywordc", "foreground", "grey", NULL);
  gtk_text_buffer_create_tag (buffer, "keyword", "font", "monospace", NULL);
  gtk_text_buffer_create_tag (buffer, "digitc", "foreground", "blue", NULL);
  gtk_text_buffer_create_tag (buffer, "digit", "weight", "900", NULL);
  gtk_container_add (GTK_CONTAINER (window), vbox);

  g_signal_connect_swapped (G_OBJECT (window), "destroy",
			    G_CALLBACK (gtk_main_quit), G_OBJECT (window));

  //gtk_text_buffer_set_text (buffer, "Hello, this is some text\n", -1);
  {
    FILE *fp = NULL;
    char *p = NULL;
    int flen = 0;
    char cc;
    int i;
    char ss[256];
    char si = 0;

    for(i=0;i<256;i++)
	ss[i]=0;

    fp = fopen ("hello.c", "r");
    fseek (fp, 0L, SEEK_END);
    flen = ftell (fp);
    fseek (fp, 0L, SEEK_SET);
    p = malloc (flen);
    fread (p, 1, flen, fp);

    gtk_text_buffer_set_text (buffer, p, -1);
    gtk_widget_show_all (window);

    int offset = 0;
    for (i = 0; i < flen; i++)
      {
	gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
	gtk_text_buffer_get_iter_at_offset (buffer, &end, offset);
	cc = gtk_text_iter_get_char (&start);
	
	if (is_token (cc))
	  {
	    if(si && offset && is_keyword((const char*)ss,si))
	    {
		//printf("%s\t",ss);
		//printf("%d\n",si);
		gtk_text_buffer_get_iter_at_offset (buffer, &start, offset-si);
		gtk_text_buffer_get_iter_at_offset (buffer, &end, offset);
		gtk_text_buffer_apply_tag_by_name (buffer, "keyword", &start,&end);
		gtk_text_buffer_apply_tag_by_name (buffer, "keywordc", &start,&end);
	    }
	    
	    si=0;
	    int t = 0;
	    for(t=0;t<256;t++)
	        ss[t]=0;
	    
	    if(cc!=' ' && cc!='\n' && cc!= '\r')
	    {
		gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
		gtk_text_buffer_get_iter_at_offset (buffer, &end, offset + 1);
		gtk_text_buffer_apply_tag_by_name (buffer, "token", &start, &end);
	    }
	  }
	  else if(isdigit(cc))
	  {
	    gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
	    gtk_text_buffer_get_iter_at_offset (buffer, &end, offset+1);
	    gtk_text_buffer_apply_tag_by_name (buffer, "digit", &start, &end);
	    gtk_text_buffer_apply_tag_by_name (buffer, "digitc", &start, &end);
	    
	  }
	  else
	  {
	    ss[si]=cc;
	    si++;
	  }

	offset++;
      }
    gtk_main ();

    free (p);
  }

  return 0;
}
